package com.yunyao.web.config.interceptor;

import com.alibaba.fastjson2.JSON;
import com.yunyao.common.config.JwtProperties;
import com.yunyao.common.constant.Constants;
import com.yunyao.common.core.BaseContext;
import com.yunyao.common.core.redis.RedisCache;
import com.yunyao.common.web.enums.ResultMsgEnum;
import com.yunyao.common.web.util.ConvertUtil;
import com.yunyao.common.web.util.YResult;
import com.yunyao.framework.service.UserService;
import com.yunyao.framework.vo.user.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import static com.yunyao.common.web.util.JwtUtil.checkJwt;

@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {
    @Autowired
    private UserService userService;
    @Autowired
    RedisCache redisCache;
    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 校验jwt
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 设置响应头
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "application/json;charset=UTF-8");
        MDC.put("traceId", UUID.randomUUID().toString().replace("-", ""));
        //判断当前拦截到的是Controller的方法还是其他资源
        if (!(handler instanceof HandlerMethod)) {
            //当前拦截到的不是动态方法，直接放行
            return true;
        }

        //1、从请求头中获取令牌
        String token = ConvertUtil.stringReplace(request.getHeader(jwtProperties.getAdminTokenName()), Constants.TOKEN_PREFIX, "");

        //2、校验令牌
        try {
            if (StringUtils.isBlank(token)) {
                //3、不通过
                response.setStatus(500);
                // 写入自定义响应体
                response.getWriter().write(JSON.toJSONString(YResult.error(ResultMsgEnum.TOKEN_NULL)));
                return false;
            }
            log.info("jwt校验:{}", token);
            if (!checkJwt(jwtProperties.getAdminSecretKey(), token) || !redisCache.hasKey(Constants.TOKEN + token)) {
                //3、不通过
                response.setStatus(500);
                // 写入自定义响应体
                response.getWriter().write(JSON.toJSONString(YResult.error(ResultMsgEnum.TOKEN_EXPIRE)));
                return false;
            }
            String userId = redisCache.getString(Constants.TOKEN + token);
            if (userId == null) {
                //3、不通过
                response.setStatus(500);
                // 写入自定义响应体
                response.getWriter().write(JSON.toJSONString(YResult.error(ResultMsgEnum.TOKEN_EXPIRE)));
                return false;
            }
            String userKey = Constants.USERID + userId;
            String userObject = redisCache.getString(userKey);
            if (userObject == null){
                UserVO userInfo = userService.getUserInfo(userId);
                if (Objects.isNull(userInfo)){
                    //3、不通过
                    response.setStatus(500);
                    // 写入自定义响应体
                    response.getWriter().write(JSON.toJSONString(YResult.error(ResultMsgEnum.USER_INFO_ERROR)));
                    return false;
                }
                BaseContext.setUserInfo(JSON.toJSONString(userInfo));
                redisCache.setCacheObject(userKey,JSON.toJSONString(userInfo),12, TimeUnit.HOURS);
            }else {
                BaseContext.setUserInfo(userObject);
            }
            BaseContext.setUserId(userId);
            return true;
        } catch (Exception ex) {
            log.error("jwt校验异常:{}", ex.getMessage());
            //4、不通过，响应401状态码
            response.setStatus(401);
            return false;
        }
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
                                Object handler, Exception ex) {
        BaseContext.removeUserId();
        BaseContext.removeUserInfo();
    }
}
